//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<XTagLayout.h>
///	@path	~/src/gui/xgui/
///	@date	2008/06/29
///	@desc	Layout has tagged text & image, animation, hyperlink or things.

#pragma once

#include "xeres.h"

#include <list>
#include <set>

#include "lib/utilities/string.h"

#include "gui/IGuiComp.h"
#include "gui/IGuiForm.h"
#include "gui/shifter.h"
#include "gui/composite/composition.h"
#include "gui/style/style.h"
#include "gui/style/uniscribe.h"
#include "gui/style/tagtext.h"
#include "gui/image/IBitmap.h"
#include "gui/image/ImageResource.h"

namespace xeres {

	/*! 
		\class	XTagLayout
		\brief	
	*/
	class XTagLayout : public IGuiControl , public TagTextBase
	{
	public:

		/// \ctor
		XTagLayout( void );

		/// \ctor
		XTagLayout( RefWeak<StyleFont> font , ImageResource * imageRes , const Rect<int>& placement );

		/// \dtor
		virtual ~XTagLayout( void );

		DECL_IOBJECT_CLASS_DYNAMIC( XTagLayout , IGuiControl );

	public:

		/// \name	XGui Component Attributes
		//@{

		/// \brief	Set parent component.
		virtual bool SetParent( RefWeak<IGuiForm> parent );

		/// \brief	Set size of component.
		virtual bool SetSize( const Pair<int>& size );

		/// \brief	Set placement.
		virtual bool SetPlacement( const Rect<int>& placement );

		//@}

		/// \name Message Passing
		//@{

		///	\brief	Process key input message.
		virtual HandleInput OnKeyInput( Updater& updater );

		///	\brief	Process mouse input message.
		virtual HandleInput OnMouseInput( Updater& updater );

		/// \brief	Call when focus in.
		virtual void OnFocusIn( Updater& updater , RefWeak<IGuiComp> last );

		/// \brief	Call when focus out.
		virtual void OnFocusOut( Updater& updater , RefWeak<IGuiComp> next );

		//@}

		/// \name Presentation Manipulation
		//@{

		/// \brief	Tick update.
		virtual void Tick( Updater& updater , float dTime );

		/// \brief	Draw XGUI component to composition.
		virtual void Draw( Composition& composition );

		//@}

		///	\brief		Set layout text.
		void SetText( const WString& text );

		/// \brief		Set image resource.
		void SetImageResource( ImageResource * imageRes );

		/// \brief		Clear layout.
		void Clear( void );

		/// \brief		Get layout height.
		size_t GetLayoutHeight( void ) const;

		/// \brief		Get line count.
		size_t GetLineCount( void ) const;

		/// \brief		Get line height.
		size_t GetLineHeight( size_t line ) const;

		/// \brief		Get line width.
		size_t GetLineWidth( size_t line ) const;

	protected:

		// Refresh layout.
		void Relayout( int line = 0 );

		// Produce line.
		void MakeLines( const wchar_t *& buffer , const Pair<int>& pos , size_t width , size_t height , TextStyle& style );

		// Flush text into line buffer.
		void FlushTexts( Line& line , const WString& buffer , Pair<int>& pos , size_t space , TextStyle& style );

		enum TagResult
		{
			TAG_STYLE ,
			TAG_IMAGE ,
			TAG_NONE ,
			TAG_NEWLINE ,
			TAG_TEXT ,
			TAG_last
		};

		// Make text tags from.
		TagResult MakeText( Tag *& tag , const WString& text , int& start , size_t width , TextStyle& style );

		// Produce Tag.
		TagResult ParseTag( Tag *& tag , const wchar_t *& buffer , const Pair<int>& pos , size_t width , TextStyle& style );

		// Append line.
		void AppendLine( const Line& line , Pair<int>& cursor );

		// Register created tag.
		void CreatedTag( Tag * created );

		// Release tag.
		void ReleaseTag( Tag * tag );

		//@ data

		// focusing rect
		Rect<int>			m_rect;

		// full text
		WString				m_buffer;

		// ticking tags
		std::set< Tag * >	m_tickTag;

		// lines
		std::deque< Line >	m_lines;

		// default font
		Ref<StyleFont> 		m_font;

		// Global uniscribe
		Uniscribe			m_uni;

		// image resource loader
		ImageResource *		m_imageRes;
	};

} // namespace xeres
